/**
 * @tag controllers, home
 * Displays a table of reports.  Lets the user 
 * ["ReportController.prototype.form submit" create], 
 * ["ReportController.prototype.&#46;edit click" edit],
 * or ["ReportController.prototype.&#46;destroy click" destroy] reports.
 */
jQuery.Controller.extend('Bugstat.Controllers.ReportController',
/* @Static */
{
    onDocument: false,
	loadedReports : [],
	visibleReports : [],
	
	reportData : {},
	
	isShowing : function ( report_id )	{
		return Bugstat.Controllers.ReportController.visibleReports[ report_id ];
	},
	
	isLoaded : function ( report_id )	{
		return Bugstat.Controllers.ReportController.loadedReports[ report_id ];
	},
	
	publishXRanges: function (el, ranges) {		
		el.controller().publish('xRangesChanged', ranges );
	},
	
	publishYRanges: function (el, group_ranges) {		
		el.controller().publish('yRangesChanged', group_ranges );
	},
	
	normalizeYRanges: function( sender ) {
		var maxY = Number.MIN_VALUE;
		var minY = 0; // TODO REPLACE WITH Number.MAX_VALUE;
		
		for (visibleReportID in Bugstat.Controllers.ReportController.visibleReports)
		{
			var visibleReport = Bugstat.Controllers.ReportController.visibleReports[visibleReportID];
			
			if ( visibleReport.group == sender.report_descriptor.group )
			{
				if ( visibleReport.minValue < minY ) minY = visibleReport.minValue;
				if ( visibleReport.maxValue > maxY ) maxY = visibleReport.maxValue;				
			}
		}

		sender.publish('yRangesChanged',  { 'group_name': sender.report_descriptor.group,
		 		 							'yRanges': {'yaxis': { 'from': minY,
																   'to': maxY } }
		       							  } );
	}
},
/* @Prototype */
{
	report_id: 0,
	report_descriptor: 0,
	report: 0,
	
	xRanges: 0,
	yRanges: 0,
	
	graph_options: {		
		colors: [ "#555", "#D55", "#DD5" ],
	    xaxis: { mode: "time" },
	    selection: { mode: "x", color: "#ccc" },
		grid: { leftBottomOnly: true, ignoreFirstTick:true },
		series: { shadowSize: 0 },
		shadowSize: 0,
		legend: { labelBoxBorderColor: null,
				  backgroundOpacity: 0,
				  noColumns: 5 }
	},
	
	initController: function(report_descriptor) {
		this.report_descriptor = report_descriptor;
		this.report_id = report_descriptor.id;
	},
	
    /**
     * Show report graph in the main view
     * @param {report} Report to show
     */
    showReport: function() {
		if ( Bugstat.Controllers.ReportController.isLoaded( this.report_id ) ) 
		{
			if ( !Bugstat.Controllers.ReportController.isShowing( this.report.id ) )
			{
				this.retrieveReportTag().show();
				
				Bugstat.Controllers.ReportController.visibleReports[this.report.id] = this.report;
				this.publish('reportShown', this.report );
			
				Bugstat.Controllers.ReportController.normalizeYRanges( this );
			
				this.plotReportGraph();
			}		
		}
		else
		{
			this.loadReport();
		}
    },

	hideReport: function() {
		this.retrieveReportTag().hide();
					
		Bugstat.Controllers.ReportController.visibleReports[this.report.id] = 0;
		this.publish('reportHidden', this.report );	
		
		Bugstat.Controllers.ReportController.normalizeYRanges( this );
    },

	loadReport: function() 
	{
		this.retrieveReportTag().html( '//bugstat/views/report/loading.ejs', this.report_descriptor );
		this.retrieveReportTag().show();
		
		Bugstat.Models.Report.findById( this.report_id, this.callback('handleReportLoaded'), this.callback('handleLoadingError') );		
	},
	
	plotReportGraph: function() {
		
		if ( Bugstat.Controllers.ReportController.isShowing( this.report_id ) )
		{
			// Create custom plot parameters (to normalize ranges)
			var params = {};			
			if ( this.xRanges) params["xaxis"] = { min: this.xRanges.xaxis.from, max: this.xRanges.xaxis.to };
			if ( this.yRanges ) params["yaxis"] = { min: this.yRanges.yaxis.from, max: this.yRanges.yaxis.to }

			// Create plot legend
			this.graph_options.legend = { container: this.retrieveLegendTagName() };			
			
			// Render the plot
			var plotTag = this.retrievePlotTag();
			var plot = $.plot( plotTag, this.reportData, $.extend( true, {}, this.graph_options, params ) );
			
			// Attach important dates to the plot
			$('body').bugstat_important_dates( "attachDatesToPlot", plotTag, plot );
		}
	},
	
	handleReportLoaded: function(report) 
	{
		if ( report )
		{
			Bugstat.Controllers.ReportController.loadedReports[report.id] = report;
							
			this.report = report;
					
			// Fix report timestamps
			this.report.fixTimestamps();
					
			this.reportData = this.createReportData(report),
					
			// Update plot options to accomadate important dates
			$('body').bugstat_important_dates( "updatePlotOptions", this.graph_options );			

			// Updaate view
			this.retrieveReportTag().addClass( report.identity() );
			this.retrieveReportTag().html('//bugstat/views/report/report.ejs',report);
					
			// Plot the report		
			this.publish('reportLoaded', report );		
			this.showReport( report );
		}
		else
		{
			this.handleLoadingError(0, 0, 'cant_load_report' )
		}
    },

	handleLoadingError : function(requset, error, status) 
	{
		var message = { name: this.report_descriptor.name,
			            error: status };

		this.retrieveReportTag().html( '//bugstat/views/report/loading_error.ejs', message );
		this.retrieveReportTag().show();
	},

	retrieveReportTag: function() {
		return $(".report_"+this.report_id);
	},
	
	retrieveLegendTagName: function() {
		return ".report_legend_" + this.report_id;
	},
	
	retrievePlotTag: function() {
		return $(".report_content_" + this.report_id);
	},
	
	createReportData: function(report) {
		
		var reportData = report.report_data;
		var captions = report.captions;
		var type = report.type;
		
		if ( type == 'GRAPH_WITH_AREAS' )
		{
			var result = new Array();

			for ( var i = 0; i < reportData[0][1].length; i++ )
			{
				var data = new Array();
				for ( var j = 0; j < reportData.length; j++ )
				{
					data[j] = new Array();
					
					data[j][0] = reportData[j][0];
					data[j][1] = reportData[j][1][i];
				}	
				
				result[i] = { data: data, label: captions[ i + 1] }
			}

			return result;
		}
		else
		{
			return [ { data: reportData, label: captions[1] } ]
		}
	},
	
	'.hideReport click': function(el){	
        var report = el.parents().model();
		this.hideReport( report );
    },    

	'xRangesChanged subscribe': function(called, ranges) {
		this.xRanges = ranges;
		
		this.plotReportGraph();
	},
	
	'yRangesChanged subscribe': function(called, group_ranges) {
		if ( group_ranges.group_name == this.report_descriptor.group &&
			 group_ranges.group_name != 'Overview')
		{	
			this.yRanges = group_ranges.yRanges;
			
			this.plotReportGraph();
		}
	}
	
});